package com.way.filemanager.navigation;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.Locale;

import android.content.Context;
import android.os.Environment;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;

public class Utils
{
    private static final String[][] MIME_MapTable = {
        { ".3gp", "video/3gpp" },
        { ".3gpp", "video/3gpp " },
        { ".3g2", "video/3gpp2" },
        { ".3gpp2", "video/3gpp2" },
        { ".apk", "application/vnd.android.package-archive" },
        { ".cer", "application/x-x509-ca-cert" },
        { ".lar", "application/vnd.android.package-archive" },
        { ".wpl", "application/vnd.ms-wpl" },
        { ".amr", "audio/amr" },
        { ".awb", "audio/amr-wb" },
        { ".asf", "video/x-ms-asf" },
        { ".avi", "video/x-msvideo" },
        { ".bin", "application/octet-stream" },
        { ".bmp", "image/bmp" },
        { ".wbmp", "image/vnd.wap.wbmp" },
        { ".c", "text/plain" },
        { ".class", "application/octet-stream" },
        { ".conf", "text/plain" },
        { ".cpp", "text/plain" },
        { ".doc", "application/msword" },
        { ".exe", "application/octet-stream" },
        { ".gif", "image/gif" },
        { ".gtar", "application/x-gtar" },
        { ".gz", "application/x-gzip" },
        { ".h", "text/plain" },
        { ".htm", "text/html" },
        { ".html", "text/html" },
        { ".jar", "application/java-archive" },
        { ".java", "text/plain" },
        { ".jpeg", "image/jpeg" },
        { ".jpg", "image/jpeg" },
        { ".js", "application/x-javascript" },
        { ".log", "text/plain" },
        { ".m3u", "audio/x-mpegurl" },
        { ".pls", "audio/x-scpls" },
        { ".m4a", "audio/mp4a-latm" },
        { ".m4b", "audio/mp4a-latm" },
        { ".m4p", "audio/mp4a-latm" },
        { ".m4u", "video/vnd.mpegurl" },
        { ".m4v", "video/x-m4v" },
        { ".mov", "video/quicktime" },
        { ".mkv", "video/x-matroska" },
        { ".mp2", "audio/x-mpeg" },
        { ".mp3", "audio/x-mpeg" },
        { ".mp4", "video/mp4" },
        { ".mpc", "application/vnd.mpohun.certificate" },
        { ".mpe", "video/mpeg" },
        { ".mpeg", "video/mpeg" },
        { ".mpg", "video/mpeg" },
        { ".mpg4", "video/mp4" },
        { ".mpga", "audio/mpeg" },
        { ".msg", "application/vnd.ms-outlook" },
        { ".ogg", "audio/ogg" },
        { ".oga", "application/ogg" },
        { ".pdf", "application/pdf" },
        { ".png", "image/png" },
        { ".pps", "application/vnd.ms-powerpoint" },
        { ".ppt", "application/vnd.ms-powerpoint" },
        { ".prop", "text/plain" },
        { ".rar", "application/x-rar-compressed" },
        { ".rc", "text/plain" },
        { ".rmvb", "audio/x-pn-realaudio" },
        { ".rtf", "application/rtf" },
        { ".sh", "text/plain" },
        { ".tar", "application/x-tar" },
        { ".tgz", "application/x-compressed" },
        { ".txt", "text/plain" },
        { ".wav", "audio/x-wav" },
        { ".wma", "audio/x-ms-wma" },
        { ".wmv", "audio/x-ms-wmv" },
        { ".wps", "application/vnd.ms-works" },
        { ".xml", "text/plain" },
        { ".z", "application/x-compress" },
        { ".zip", "application/zip" },
        { ".aac", "audio/aac" },
        { ".mid", "audio/midi" },
        { ".midi", "audio/midi" },
        { ".xmf", "audio/midi" },
        { ".rtttl", "audio/midi" },
        { ".smf", "audio/sp-midi" },
        { ".imy", "audio/imelody" },
        { ".rtx", "audio/midi" },
        { ".ota", "audio/midi" },
        { "", "*/*" }
    };

    public static String getMimeType(File file)
    {
        String type = "application/unknown";
        String fullPath = file.getPath();
        // search for .
        int dotIndex = fullPath.lastIndexOf(".");
        if (dotIndex < 0)
        {
            return type;
        }

        /* get extention */
        String ext = fullPath.substring(dotIndex, fullPath.length()).toLowerCase(Locale.getDefault());
        if (ext == "")
            return type;

        // search MIME list for match mime type
        for (int i = 0; i < MIME_MapTable.length; i++)
        {
            if (ext.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }

    private final static class FileCompare
    {
        FileCompare(File f)
        {
            file = f;
            isDir = f.isDirectory();
        }
        File file;
        String name;
        long size;
        long time;
        String type;
        boolean isDir;
    }

    private final static FileCompare getN(File f)
    {
        FileCompare ret = new FileCompare(f);
        ret.name = f.getName();
        ret.time = f.lastModified();
        return ret;
    }

    private final static FileCompare getS(File f)
    {
        FileCompare ret = new FileCompare(f);
        ret.size = f.length();
        ret.time = f.lastModified();
        return ret;
    }

    private final static FileCompare getT(File f)
    {
        FileCompare ret = new FileCompare(f);
        ret.time = f.lastModified();
        return ret;
    }

    private final static FileCompare getP(File f)
    {
        FileCompare ret = new FileCompare(f);
        ret.name = f.getName();
        ret.time = f.lastModified();
        if(ret.isDir)
        {
            ret.type = null;
        }
        else
        {
            String name = ret.name;
            int intDot = name.lastIndexOf(".");
            ret.type = intDot > 0 ? name.substring(intDot) :"";
        }
        return ret;
    }

    public static File[] reorderFilesByName(File[] files)
    {
        if(files == null)
        {
            return null;
        }

        final int len = files.length;
        FileCompare[] fc = new FileCompare[len];
        for(int i = 0 ; i< len ; i++)
        {
            fc[i] = getN(files[i]);
        }

        FileCompare fcI;
        FileCompare fcJ;
        for(int i = 0 ; i< len - 1 ; i++)
        {
            for(int j = i + 1 ; j < len ; j++)
            {
                int c;
                fcI = fc[i];
                fcJ = fc[j];
                if(fcI.isDir^fcJ.isDir)
                {
                    if(!fcI.isDir)
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
                else
                {
                    c = fcI.name.compareToIgnoreCase(fcJ.name);
                    if (c > 0 || ((c == 0) && (fcI.time < fcJ.time)))
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
            }
        }

        for(int i = 0 ; i< len ; i++)
        {
            files[i] = fc[i].file;
        }

        return files;
    }

    public static File[] reorderFilesBySize(File[] files)
    {
        if(files == null)
        {
            return null;
        }

        final int len = files.length;

        FileCompare[] fc = new FileCompare[len];
        for(int i = 0 ; i< len ; i++)
        {
            fc[i] = getS(files[i]);
        }

        for(int i = 0 ; i< len - 1 ; i++)
        {
            for(int j = i + 1 ; j < len ; j++)
            {
                if(fc[i].isDir^fc[j].isDir)
                {
                    if(!fc[i].isDir)
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
                else
                {
                    if (fc[i].size > fc[j].size || ((fc[i].size == fc[j].size) && (fc[i].time < fc[j].time)))
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
            }
        }
        for(int i = 0 ; i< len ; i++)
        {
            files[i] = fc[i].file;
        }
        return files;
    }

    public static File[] reorderFilesByTime(File[] files)
    {
        if(files == null)
        {
            return null;
        }

        final int len = files.length;

        FileCompare[] fc = new FileCompare[len];
        for(int i = 0 ; i< len ; i++)
        {
            fc[i] = getT(files[i]);
        }

        for(int i = 0 ; i< len - 1 ; i++)
        {
            for(int j = i + 1 ; j < len ; j++)
            {
                if(fc[i].isDir^fc[j].isDir)
                {
                    if(!fc[i].isDir)
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
                else
                {
                    if ((fc[i].time < fc[j].time))
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
            }
        }
        for(int i = 0 ; i< len ; i++)
        {
            files[i] = fc[i].file;
        }
        return files;
    }


    public static File[] reorderFilesByType(File[] files)
    {
        if(files == null)
        {
            return null;
        }

        final int len = files.length;

        FileCompare[] fc = new FileCompare[len];
        for(int i = 0 ; i< len ; i++)
        {
            fc[i] = getP(files[i]);
        }

        FileCompare fcI;
        FileCompare fcJ;

        for(int i = 0 ; i< len - 1 ; i++)
        {
            for(int j = i + 1 ; j < len ; j++)
            {
                fcI = fc[i];
                fcJ = fc[j];
                if(fc[i].isDir^fc[j].isDir)
                {
                    if(!fc[i].isDir)
                    {
                        FileCompare temp = fc[i];
                        fc[i] = fc[j];
                        fc[j] = temp;
                    }
                }
                else
                {
                    if(fcI.type != null && fcJ.type != null)
                    {
                        int c = fcI.type.compareToIgnoreCase(fcJ.type);
                        if (c > 0 || ((c == 0) && (fcI.time < fcJ.time)))
                        {
                            FileCompare temp = fc[i];
                            fc[i] = fc[j];
                            fc[j] = temp;
                        }
                    }
                    else
                    {
                        if (fcJ.type == null)
                        {
                            FileCompare temp = fc[i];
                            fc[i] = fc[j];
                            fc[j] = temp;
                        }
                    }
                }
            }
        }
        for(int i = 0 ; i< len ; i++)
        {
            files[i] = fc[i].file;
        }
        return files;
    }

    public static String createTimeFormat(long time)
    {
        SimpleDateFormat formatter = new  SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
        Calendar cal = Calendar.getInstance();
        if(time == 0)
            time = System.currentTimeMillis();
        cal.setTimeInMillis(time);
        return formatter.format(cal.getTime());
    }

    public static String formetFileSize(long fileS)
    {
        if(fileS == 0)
        {
            return "0 M";
        }
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "K";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "M";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "G";
        }
        return fileSizeString;
    }

    public static interface FileBytesListener
    {
        boolean onProgress(long bytes);
    }

    private static void listAllDeleteFiles(File file, LinkedList<File> add)
    {
        if(file.isDirectory())
        {
            File[] files = file.listFiles();
            if(files != null && files.length > 0)
            {
                for(File f : files)
                {
                    if(f.isFile())
                    {
                        add.add(f);
                    }
                    else if(f.isDirectory())
                    {
                        listAllDeleteFiles(f, add);
                    }
                }
            }
        }
        add.add(file);
    }

    public static LinkedList<File> listAllDeleteFiles(LinkedList<File> files)
    {
        LinkedList<File> ret = new LinkedList<File>();
        for(File f : files)
        {
            if(f.exists() && f.canWrite())
            {
                listAllDeleteFiles(f, ret);
            }
        }

        return ret;
    }

    public static class FileFT
    {
        public FileFT(File f, File t)
        {
            file = f;
            to = t;
        }
        File file;
        File to;
    }

    public static class FileFTs extends LinkedList<FileFT>
    {
        private static final long serialVersionUID = 3646567L;
        long length;
        @Override
        public boolean add (FileFT f)
        {
            length += f.file.length();
            return super.add(f);
        }
    }

    private static boolean doCopySingleFile(final File from, final File to, FileBytesListener l)
    {
        boolean ret = true;
        try {
            int byteRread = 0;
            if (from != null && from.exists())
            {
                MyFileManager.log("copy "+to.getAbsolutePath());
                boolean delTo = false;
                InputStream inStream = new FileInputStream(from);
                FileOutputStream fs = new FileOutputStream(to);
                byte[] buffer = new byte[1024];
                while ((byteRread = inStream.read(buffer)) != -1)
                {
                    fs.write(buffer, 0, byteRread);
                    if(l != null)
                    {
                        if(l.onProgress(byteRread) == false)
                        {
                            delTo = true;
                            break;
                        }
                    }
                }
                fs.flush();
                fs.close();
                inStream.close();
                if(delTo == true)
                {
                    to.delete();
                    MyFileManager.log("del "+to.getAbsolutePath());
                }
            }
            else
            {
                ret = false;
                MyFileManager.log("doCopySingleFile "+from.getAbsolutePath()+" doesnot exists"
                        , new Exception("doCopySingleFile"));
            }
        } catch (IOException e) {
            ret = false;
            MyFileManager.log("doCopyFolder fail ", e);
        }
        return ret;
    }

    public static boolean copyListedFile(File from, File to, FileBytesListener l)
    {
        if(from == null || to == null)
        {
            MyFileManager.log("copyListedFile param fail");
            return false;
        }

        if(from.isFile() == true)
        {
            return doCopySingleFile(from, to, l);
        }
        else
        {
            to.mkdirs();
            if(l != null)
            {
                l.onProgress(from.length());
            }
            return true;
        }
    }

    private static void listFileForCopy(File from, File to, FileFTs ft)
    {
        ft.add(new FileFT(from, to));
        if(from.isDirectory())
        {
            File[] files = from.listFiles();
            if(files != null && files.length > 0)
            {
                for(File f : files)
                {
                    File dst = new File(to.getAbsolutePath() + File.separator + f.getName());
                    if(f.isFile())
                    {
                        ft.add(new FileFT(f, dst));
                    }
                    else if(f.isDirectory())
                    {
                        listFileForCopy(f, dst, ft);
                    }
                }
            }
        }
    }

    public static FileFTs listFileForCopy(LinkedList<File> files, File to)
    {
        FileFTs ret = new FileFTs();

        if(files == null || files.size() <= 0 || to == null || to.isDirectory() == false)
        {
            MyFileManager.log("listFileForCopy param fail", new Exception("listFileForCopy"));
            return ret;
        }

        StringBuilder dstFileName = new StringBuilder();

        for(File f : files)
        {
            if(f.exists())
            {
                dstFileName.delete(0, dstFileName.length());
                String fName = f.getName();
                dstFileName.append(to.getAbsolutePath()).append(File.separator).append(fName);

                File dstFile = new File(dstFileName.toString());
                int count = 1;
                if(dstFile.exists())
                {
                    int insertIndex = dstFileName.length();
                    int dotIndex = fName.lastIndexOf(".");
                    String sub = "";
                    if(dotIndex > 0)
                    {
                        insertIndex = insertIndex - (fName.length() - dotIndex);
                        sub = fName.substring(dotIndex);
                    }

                    while(dstFile.exists())
                    {
                        dstFileName.setLength(insertIndex);
                        dstFile = new File(dstFileName.append("(").append(count).append(")").append(sub).toString());
                        count++;
                    }


                }
                listFileForCopy(f, dstFile, ret);
            }
        }

        return ret;
    }
    public static LinkedList<File> listFileForUpload(LinkedList<File> files){
        LinkedList<File> ret= new LinkedList<File>();
        if(files == null || files.size() <= 0){
            Log.e("FileListRe","listFileForUpload error------------");
            return ret;
        }
        for(File f : files) {
            if(f.exists()){
                listFileForUploadRecursive(f,ret);
            }
        }
        return ret;
    }
    public static void listFileForUploadRecursive(File from,LinkedList<File> list){
        list.add(from);
        if(from.isDirectory()) {
            File[] files = from.listFiles();
            if(files != null && files.length > 0){
                for(File f : files){
                    if(f.isFile()){
                        list.add(f);
                    }else if(f.isDirectory()){
                        listFileForUploadRecursive(f,list);
                    }
                }
            }
        }

    }


}
